/**
 * @description 常用的网络校验
 */
import { getCIDR } from '@/utils/network.js';
import { errorCode } from '@/constant/dict';
import { REGULAR_RULES } from '@/constant/regularRules';
export default {
    data() {
        return {
            lanIp: '',
            mask: '',
            dhcpStart: '',
            dhcpEnd: ''
        };
    },
    created() {
        this.getLanIpAndMask();
    },
    methods: {
        /**
         * @description ip表单校验,使用ip最后一段的校验
         */
        ipLastValid(rule, value, callback) {
            if (!value) {
                return callback(new Error(this.$t('errorTips.cannotBeEmpty')));
            }
            const numberValue = +value;
            let tmp = this.lanIp.split('.');
            const lanPrefix = tmp[0] + '.' + tmp[1] + '.' + tmp[2] + '.';
            const fullIp = `${lanPrefix}${numberValue}`;
            this.ipErrorValid(fullIp, callback);
            return callback();
        },

        /**
         * @description ip通用错误校验
         */
        ipErrorValid(validIp, callback) {
            if (!validIp) {
                return callback(new Error(this.$t('errorTips.cannotBeEmpty')));
            }

            if (!REGULAR_RULES.IPV4.test(validIp)) {
                return callback(new Error(this.$t('security.ipFilter.illegalIP')));
            }

            const isInNetworkSegment = this.validNetworkSegment(validIp);

            const validRes = this.validBroadAndNetwork(validIp);

            if (typeof isInNetworkSegment === 'string') {
                return callback(new Error(isInNetworkSegment));
            }

            if (validRes === errorCode.EQUAL_LAN_IP_ADDRESS) {
                return callback(new Error(this.$t('netWork.lanSettings.equalsRouter')));
            }

            if (validRes === errorCode.EQUAL_BROAD_ADDRESS) {
                return callback(new Error(this.$t('netWork.lanSettings.lanIpNotEqualBroadCastAddress')));
            }

            if (validRes === errorCode.EQUAL_NETWORK_ADDRESS) {
                return callback(new Error(this.$t('netWork.lanSettings.lanIpNotEqualNetworkAddress')));
            }
        },
        /**
         * @description 获取lanIp和Mask节点数据
         */
        async getLanIpAndMask() {
            let arr = ['MODULE_LAN_IP', 'MODULE_LAN_NETMASK'];
            const res = await this.$getNodeFromServer(...arr).catch((err) => {
                console.log(err);
            });
            if (res) {
                const { MODULE_LAN_IP, MODULE_LAN_NETMASK } = res;
                this.lanIp = MODULE_LAN_IP;
                this.mask = MODULE_LAN_NETMASK;
            }
        },

        /**
         * @description 获取 DHCP Range 节点值
         */
        async getDhcpRange() {
            let arr = ['MODULE_LAN_DHCPSTART', 'MODULE_LAN_DHCPEND'];
            const res = await this.$getNodeFromServer(...arr).catch((err) => {
                console.log(err);
            });
            if (res) {
                const { MODULE_LAN_DHCPSTART, MODULE_LAN_DHCPEND } = res;
                this.dhcpStart = MODULE_LAN_DHCPSTART;
                this.dhcpEnd = MODULE_LAN_DHCPEND;
            }
        },

        /**
         * @description 判断ip地址是否在 Dhcp Range 中
         * @param {String|Number} ip ip地址 或者 ip地址最后一段
         * @param {String|Number} dhcpRange 地址池范围，默认从节点获取
         * @returns Boolean true-pass false-no pass
         */
        isIPInDHCPRange(ip, dhcpRange = [this.dhcpStart, this.dhcpEnd]) {
            const [startIP, endIP] = dhcpRange;
            const numberIp = +ip;
            if (!isNaN(numberIp)) {
                const startLastIp = +startIP.split('.')[3];
                const endLastIp = +endIP.split('.')[3];
                return ip >= startLastIp && ip <= endLastIp;
            } else {
                const ipNumber = this.ipToInt(ip);
                const startIPNumber = this.ipToInt(startIP);
                const endIPNumber = this.ipToInt(endIP);
                return ipNumber >= startIPNumber && ipNumber <= endIPNumber;
            }
        },

        /**
         * @description ip格式字符串转数字
         * @param {*} ip such as: 192.168.1.1
         * @returns {number} Number
         */
        ipToInt(ip) {
            const parts = ip.split('.').map(Number);
            return (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3];
        },

        /**
         * @param {*} intValue such as: -1062731520
         * @returns {string} 192.168.1.0
         */
        intToIP(intValue) {
            // 将32位整数转换为点分十进制的IP地址
            return (intValue >>> 24) + '.' + ((intValue >> 16) & 255) + '.' + ((intValue >> 8) & 255) + '.' + (intValue & 255);
        },

        /**
         * @description 校验网络地址和广播地址和LanIp
         * @param {*} ip
         * @returns errorCode or Boolean
         */
        validBroadAndNetwork(ip, lanIp = this.lanIp) {
            if (typeof ip === 'string') {
                const { broadcastAddress, networkAddress } = getCIDR(lanIp, this.mask);
                if (this.ipToInt(ip) === this.ipToInt(lanIp)) {
                    return errorCode.EQUAL_LAN_IP_ADDRESS;
                }
                if (ip === broadcastAddress) {
                    return errorCode.EQUAL_BROAD_ADDRESS;
                }
                if (ip === networkAddress) {
                    return errorCode.EQUAL_NETWORK_ADDRESS;
                }
            } else {
                return false;
            }
        },

        /**
         * @description 计算网段，最大最小ip
         * @param {*} subnet lanIp
         * @param {*} mask 子网掩码
         * @returns minIp，maxIp，允许的网段范围，最大最小值
         */
        calculateMinMaxIP(subnet, mask) {
            // 将子网和掩码转换为32位整数
            const subnetInt = this.ipToInt(subnet);
            const maskInt = this.ipToInt(mask);

            // 计算子网的起始和结束地址
            const subnetStart = subnetInt & maskInt;
            const subnetEnd = subnetStart | (~maskInt >>> 0); // 通过无符号右移处理负数

            // 将起始和结束地址转换为点分十进制的形式
            const minIP = this.intToIP(subnetStart);
            const maxIP = this.intToIP(subnetEnd);

            return { minIP, maxIP };
        },

        /**
         * @description 校验ip是否在网段内
         * @param {string} ip 需要判断的ip
         * @param {string} [lanIp=this.lanIp]
         * @param {string} [mask=this.mask]
         */
        validNetworkSegment(ip, lanIp = this.lanIp, mask = this.mask) {
            // 将IP地址和子网掩码转换为32位整数
            const ipInt = this.ipToInt(ip);
            const subnetInt = this.ipToInt(lanIp);
            const maskInt = this.ipToInt(mask);

            // 计算子网的起始和结束地址
            const subnetStart = subnetInt & maskInt;
            const subnetEnd = subnetStart | (~maskInt >>> 0); // 通过无符号右移处理负数

            // 检查IP地址是否在子网范围内
            if (ipInt >= subnetStart && ipInt <= subnetEnd) {
                return true;
            } else {
                return `${this.intToIP(subnetStart)}~${this.intToIP(subnetEnd)}`;
            }
        }
    }
};
